#include <stdio.h>
#include <pcap/pcap.h>
#include <arpa/inet.h>

struct mac_hread
{
    unsigned char srcmac[6];
    unsigned char dstmac[6];
    unsigned short type;
};

struct ip_hread
{
    unsigned char vers:4;
    unsigned char hdlen:4;
    unsigned char servtype;
    unsigned short alllen;
    unsigned short tag;
    unsigned short offset;
    unsigned char ttl;
    unsigned char protype;
    unsigned short checksum;
    unsigned int src_ip;
    unsigned int dst_ip;
   // unsigned int option;
};

struct udp_date
{
    unsigned short srcport;
    unsigned short dstport;
    unsigned short udplen;
    unsigned short checksum;
    unsigned char text[1024];
};


void deal_packet_data(u_char *userarg, const struct pcap_pkthdr *pkthdr, const u_char *packet);
int main(int argc, char const *argv[])
{
    // 1、创建pcap句柄
    pcap_t *pt = pcap_open_live("ens33", 1500, 0, 0, NULL);
    if (pt == NULL)
    {
        perror("pcap_open_live");
        return 0;
    }
    //设置过滤规则
    //编译过滤规则
    //char buf[] = "ip src host 192.168.1.47 and udp src port 9008";
    char buf[] = "ip src host 192.168.1.32 and udp src port 8080";
    struct bpf_program program;
    if (pcap_compile(pt, &program, buf, 0, 0xffffff00) == 0)
    {
        //设置过滤规则
        pcap_setfilter(pt, &program);
    }

    //捕获网络数据
#if 0
    while (1)
    {
        struct pcap_pkthdr h;
        // text保存的是帧数据的 首元素地址
        u_char *text = (u_char *)pcap_next(pt, &h);
        printf("帧数的长度:%u\n", h.len);
    }
#else
    //第二个参数-1表示一直接收
    //每收到一个数据 触发回调函数执行
    pcap_loop(pt, -1, deal_packet_data, NULL); //带阻塞
#endif

    //关闭pcap句柄
    pcap_close(pt);
    return 0;
}
void deal_packet_data(u_char *userarg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
    printf("帧数的长度:%u\n", pkthdr->len);
    // packet保存的是帧数据的首元素地址
    struct mac_hread *mac_h = (struct mac_hread *)packet;
    //mac头的分析
    char src_mac[18] = "";
    char dst_mac[18] = "";
    sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
            mac_h->dstmac[0], mac_h->dstmac[1], mac_h->dstmac[2], mac_h->dstmac[3], mac_h->dstmac[4], mac_h->dstmac[5]);
    sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
            mac_h->srcmac[0], mac_h->srcmac[1], mac_h->srcmac[2], mac_h->srcmac[3], mac_h->srcmac[4], mac_h->srcmac[5]);
    printf("mac:%s-->%s\n", src_mac, dst_mac);
    unsigned short pro = ntohs(mac_h->type);
    if (pro == 0x0800) // IP报文
    {
        
        struct ip_hread * ip_h = (struct ip_hread *)(packet+14);
        struct udp_date * data = (struct udp_date *)(packet+34);
        char ip_src_str[INET_ADDRSTRLEN] = "";//存储后面转换成字符串的ip
        inet_ntop(AF_INET,&ip_h->src_ip,ip_src_str,sizeof(ip_src_str));
        char ip_dst_str[INET_ADDRSTRLEN] = "";//存储后面转换成字符串的ip
        inet_ntop(AF_INET,&ip_h->dst_ip,ip_dst_str,sizeof(ip_dst_str));
        printf("ip:%s(%d)-->%s(%d)\n",ip_src_str,ntohs(data->srcport),ip_dst_str,ntohs(data->dstport));
        printf("text:%s\n",data->text);

    }
}